package com.tsyz.servlet.interceptor;

import com.tsyz.servlet.util.TraceIdUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Trace ID拦截器，负责生成和传递TraceId
 * 继承自BaseInterceptor，复用通用功能
 */
@Slf4j
@Component
public class TsyzTraceIdInterceptor extends BaseInterceptor {

    /**
     * 预处理方法，在请求处理之前执行
     *
     * @param request  HTTP请求对象
     * @param response HTTP响应对象
     * @param handler  处理器对象
     * @return boolean 总是返回true，表示继续执行后续处理
     */
    @Override
    protected boolean doPreHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // TraceId已在BaseInterceptor中确保存在，这里可以添加其他逻辑

        // 获取请求相关信息并记录
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        String traceId = MDC.get(TraceIdUtil.TRACE_ID);

        log.info("[traceId:{}] >>> 开始处理请求: {} {} <<<", traceId, method, requestURI);

        return true; // 返回true继续执行，false中断执行
    }

    /**
     * 后处理方法，在请求处理完成后、视图渲染之前执行
     *
     * @param request      HTTP请求对象
     * @param response     HTTP响应对象
     * @param handler      处理器对象
     * @param modelAndView 模型和视图对象
     */
    @Override
    protected void doPostHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在视图渲染之前，将traceId添加到model中（如果使用模板引擎如Thymeleaf、Freemarker等）
        if (modelAndView != null) {
            String traceId = MDC.get(TraceIdUtil.TRACE_ID);
            if (traceId != null) {
                modelAndView.addObject(TraceIdUtil.TRACE_ID, traceId);
            }
        }
    }

    /**
     * 请求完成后的回调方法，在请求完全结束后执行
     *
     * @param request  HTTP请求对象
     * @param response HTTP响应对象
     * @param handler  处理器对象
     * @param ex       处理过程中抛出的异常
     */
    @Override
    protected void doAfterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 特别注意：不在拦截器中清理MDC，而是由Filter统一清理
        // 这样设计的原因：
        // 1. 避免重复清理
        // 2. 确保在任何情况下（包括异常情况）都能清理
        // 3. 保持清理逻辑的单一性
    }
}
